package com.agh.portal.domain;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.EntityManager;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.TypedQuery;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.jpa.activerecord.RooJpaActiveRecord;
import org.springframework.roo.addon.tostring.RooToString;

import com.agh.portal.data.Votable;
import com.agh.portal.domain.enumeration.PostCategory;

@RooJavaBean
@RooToString
@RooJpaActiveRecord(finders = { "findMainPagePostsByStudent", "findMainPagePostsByTitleLike", "findMainPagePostsByTitleAndContentLike", "findMainPagePostsByCreationDateBetween" })
public class MainPagePost implements Votable{

    @Size(max = 80)
    @NotEmpty
    private String title;

    @Size(max = 300)
    @NotEmpty
    private String subtitle;

    @Size(max = 5000)
    @NotEmpty
    private String content;

    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "M-")
    private Date creationDate;

    @Enumerated
    private PostCategory category;

    private Integer goodVoteCount = 0;

    private Integer badVoteCount = 0;

    @ManyToOne
    @NotNull
    private Student student;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "mainPagePost")
    private Set<Comment> comments = new HashSet<Comment>();
    
    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Set<Student> proVoters = new HashSet<Student>();

    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Set<Student> conVoters = new HashSet<Student>();

    public String toString() {
        return "[ title=" + title + " subtitle=" + subtitle + " creationDate=" + creationDate + " creationDate=" + category + " goodVoteCount=" + goodVoteCount + " badVoteCount=" + badVoteCount + " student=" + student + "]";
    }
    
    public void addGoodVote(){
    	this.goodVoteCount++;
    }
    
    public void decrementGoodVote(){
    	this.goodVoteCount--;
    }
    
    public void addBadVote(){
    	this.badVoteCount++;
    }
    
    public void decrementBadVote(){
    	this.badVoteCount--;
    }
    
    public static TypedQuery<MainPagePost> findLatestMainPagePostsByStudent(Student student, Integer maxResults) {
        if (student == null) throw new IllegalArgumentException("The student argument is required");
        EntityManager em = MainPagePost.entityManager();
        TypedQuery<MainPagePost> q = em.createQuery("SELECT o FROM MainPagePost AS o WHERE o.student = :student ORDER BY o.creationDate desc", MainPagePost.class);
        q.setParameter("student", student);
        if(maxResults != null){
        	q.setMaxResults(maxResults);
        }
        return q;
    }
    
    public static TypedQuery<MainPagePost> findMainPagePostEntriesByCategory(PostCategory category, int firstResult, int maxResults, String sortFieldName, String sortOrder) {
        if (category == null) throw new IllegalArgumentException("The category argument is required");
        EntityManager em = MainPagePost.entityManager();
        String jpaQuery = "SELECT o FROM MainPagePost AS o WHERE o.category = :category";
        if (fieldNames4OrderClauseFilter.contains(sortFieldName)) {
            jpaQuery = jpaQuery + " ORDER BY " + sortFieldName;
            if ("ASC".equalsIgnoreCase(sortOrder) || "DESC".equalsIgnoreCase(sortOrder)) {
                jpaQuery = jpaQuery + " " + sortOrder;
            }
        }
        TypedQuery<MainPagePost> q = em.createQuery(jpaQuery, MainPagePost.class).setFirstResult(firstResult).setMaxResults(maxResults);
        q.setParameter("category", category);
        return q;
    }
    
}
